'''
* This is the projet for Brtc LlmOps Platform
* @Author Leon-liao <liaosiliang@alltman.com>
* @Description //TODO 
* @File: builtin_tool_service.py
* @Time: 2025/9/22
* @All Rights Reserve By Brtc
'''
import mimetypes
import os.path
from dataclasses import dataclass
from typing import Any

from injector import inject
from pydantic import BaseModel

from internal.core.tools.builtin_tools.categories import BuiltinCategoryManager
from internal.core.tools.builtin_tools.providers import BuiltinProviderManager
from internal.exception.exception import NotFoundException


@inject
@dataclass
class BuiltinToolService:
    """内置工具管理器"""
    builtin_tool_manager:BuiltinProviderManager
    category_manager:BuiltinCategoryManager
    def get_builtin_tools(self)->list:
        # 1、获取所有提供商提供的工具信息
        providers = self.builtin_tool_manager.get_providers()
        #2、遍历所有的工具
        builtin_tools = []
        for provider in providers:
            provider_entity = provider.provider_entity
            builtin_tool = {
                **provider_entity.model_dump(exclude=["icon"]),
                "tools":[]
            }

            #3、循环遍历所有提供商的工具
            for tool_entity in provider.get_tool_entities():
                #4、从提供者中获取工具函数
                tool = provider.get_tool(tool_entity.name)
                #5、构建工具实体
                tool_dict = {
                    **tool_entity.model_dump(),
                    "inputs":self.get_tool_inputs(tool)
                }
                builtin_tool["tools"].append(tool_dict)
            builtin_tools.append(builtin_tool)
        return builtin_tools

    def get_provider_tool(self, provider_name:str, tool_name:str)->dict:
        """根据传递的提供商名字 + 工具名字 获取指定工具信息"""
        #1、获取提供商
        provider = self.builtin_tool_manager.get_provider(provider_name)

        if provider is None:
            raise NotFoundException(f"该工具提供商{provider_name} 不存在！")

        #2、获取该提供商下对应的工具
        tool_entity  = provider.get_tool_entity(tool_name)
        if tool_entity is None:
            raise NotFoundException(f"该工具不存在{tool_name}不存在！！")
        #3、组装提供商下对应的工具信息
        provider_entity = provider.provider_entity
        tool = provider.get_tool(tool_name)

        builtin_tool = {
            "provider":{**provider_entity.model_dump(exclude=["icon", "create_at"])},
            **tool_entity.model_dump(),
            "create_at":provider_entity.create_at,
            "inputs":self.get_tool_inputs(tool)
        }

        return builtin_tool

    def get_provider_icon(self, provider_name:str)->tuple[bytes, str]:
        """根据传递的提供者，获取icon 的图标流信息"""
        # 1、获取对应的工具提供者信息
        provider = self.builtin_tool_manager.get_provider(provider_name)
        if not provider:
            raise NotFoundException(f"该工具提供者{provider_name}不存在！！")

        # 2、获取项目的根地址
        root_path = os.getcwd()

        #3、拼接得到的提供者所在文件夹
        provider_path = os.path.join(
            root_path,
            "internal","core","tools", "builtin_tools", "providers", provider_name
        )

        #4、拼接得到icon对应的路径
        icon_path = os.path.join(provider_path, "_asset", provider.provider_entity.icon)

        #5、检测icon 是否存在
        if not os.path.exists(icon_path):
            raise NotFoundException(f"该工具提供者{icon_path}没有icon文件")

        #6、读取icon 的类型
        mimetype,_=mimetypes.guess_type(icon_path)
        mimetype = mimetype or "application/octet-stream"
        #7、读取icon 的字节数据
        with open(icon_path, "rb") as f:
            byte_data = f.read()
            return byte_data, mimetype

    def get_categories(self)->list[dict[str,Any]]:
        """获取所有内置分类信息"""
        category_map =self.category_manager.get_category_map()
        return [{
            "name":category["entity"].name,
            "category":category["entity"].category,
            "icon":category["icon"]
        } for category in category_map.values()]


    @classmethod
    def get_tool_inputs(cls, tool)->list:
        """根据传入的工具，获取工具的inputs信息"""
        inputs = []
        if hasattr(tool,"args_schema") and issubclass(tool.args_schema, BaseModel):
            for field_name, model_field in tool.args_schema.model_fields.items():
                inputs.append({
                    "name":field_name,
                    "description":model_field.description or "",
                    "required":model_field.is_required(),
                    "type":model_field.annotation.__name__
                })
        return inputs


